home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / game / shoot / athrust.lha / AmigaThrust / src / soundIt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-05  |  8.9 KB  |  380 lines

  1. /*
  2.  * Paula SoundIt library V0.1
  3.  * Written by Frank Wille, frank@phoenix.owl.de
  4.  *
  5.  * Amiga specific sound routines for Thrust,
  6.  * based on SoundIt library 0.04,
  7.  * Copyright 1994 Brad Pitzel  pitzel@cs.sfu.ca
  8.  *
  9.  */
  10.  
  11. #ifdef HAVE_CONFIG_H
  12. # include "config.h"
  13. #endif
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17.  
  18. #include <exec/types.h>
  19. #include <exec/memory.h>
  20. #include <exec/errors.h>
  21. #include <graphics/gfxbase.h>
  22. #include <devices/audio.h>
  23. #include <proto/exec.h>
  24. #include <clib/alib_protos.h>
  25. #ifdef __PPC__
  26. #ifdef WOS
  27. #include <clib/powerpc_protos.h>
  28. #else
  29. #include <powerup/gcclib/powerup_protos.h>
  30. #endif
  31. #endif
  32.  
  33. #include "soundIt.h"
  34.  
  35.  
  36. struct Channel {
  37.   struct MsgPort *audmp;
  38.   struct IOAudio *audio;
  39. };
  40.  
  41.  
  42. static Sample *sounds = NULL;         /* ptr to array of samples */
  43. static int num_sounds = 0;            /* number of sounds in array above */
  44. static struct Channel chans[ADHARD_CHANNELS] = { 0 };
  45. static int num_chans = 0;
  46. static UWORD playback_period;
  47. static UBYTE chmask;
  48. static struct IOAudio *aud_io = NULL;
  49. static int audio_dev = -1;            /* 0 if audio.device is open */
  50.  
  51.  
  52.  
  53. static void free_chip_sample(Sample *s)
  54. /* free Chip RAM for a single sample */
  55. {
  56.   if (s->cdata) {
  57. #ifdef __PPC__
  58. #ifdef WOS
  59.     FreeVecPPC(s->cdata);
  60. #else
  61.     PPCFreeVec(s->cdata);
  62. #endif
  63. #else
  64.     FreeVec(s->cdata);
  65. #endif
  66.     s->cdata = NULL;
  67.   }
  68. }
  69.  
  70.  
  71. static void free_chip(void)
  72. /* free Chip RAM for Amiga samples */
  73. {
  74.   int i;
  75.  
  76.   if (sounds) {
  77.     for (i=0; i<num_sounds; free_chip_sample(&sounds[i++]));
  78.     sounds = NULL;
  79.     num_sounds = 0;
  80.   }
  81. }
  82.  
  83.  
  84. static void free_sample(Sample *s)
  85. /* free all sample buffers, remove it completely */
  86. {
  87.   if (s->data) {
  88. #if 0  /* dangerous, if buffer was not assigned by Snd_loadRawSample() */
  89.     free(s->data);
  90. #endif
  91.     s->data = NULL;
  92.   }
  93.   free_chip_sample(s);
  94.   s->len = s->loop = 0;
  95. }
  96.  
  97.  
  98. static unsigned char *get_chip_sample(Sample *s)
  99. /* allocate enough Chip-RAM, then convert sample to Amiga format. */
  100. {
  101.   unsigned char *dest,*src=s->data,*buf=NULL;
  102.   int i = s->len;
  103.  
  104.   if (i <= 0)
  105.     return (NULL);
  106. #ifdef __PPC__
  107. #ifdef WOS
  108.   if (buf = (unsigned char *)AllocVecPPC(i,MEMF_CHIP|MEMF_PUBLIC,0)) {
  109. #else
  110.   if (buf = (unsigned char *)PPCAllocVec(i,MEMF_CHIP|MEMF_PUBLIC)) {
  111. #endif
  112. #else /* M68k */
  113.   if (buf = (unsigned char *)AllocVec(i,MEMF_CHIP|MEMF_PUBLIC)) {
  114. #endif
  115.     dest = buf;
  116.     do
  117.       *dest++ = (*src++)-0x80;
  118.     while (--i);
  119.   }
  120.   return (buf);
  121. }
  122.  
  123.  
  124. static struct IOAudio *alloc_ioaudio(void)
  125. {
  126. #ifdef __PPC__
  127. #ifdef WOS
  128.   return ((struct IOAudio *)AllocVecPPC(sizeof(struct IOAudio),
  129.                                         MEMF_PUBLIC,0));
  130. #else
  131.   return ((struct IOAudio *)PPCAllocVec(sizeof(struct IOAudio),
  132.                                         MEMF_PUBLIC));
  133. #endif
  134. #else /* M68k */
  135.   return ((struct IOAudio *)AllocVec(sizeof(struct IOAudio),
  136.                                      MEMF_PUBLIC));
  137. #endif
  138. }
  139.  
  140.  
  141. static void free_ioaudio(struct IOAudio *ioa)
  142. {
  143.   int i=-1;
  144.  
  145.   if (ioa) {
  146.     ioa->ioa_Request.io_Message.mn_Node.ln_Type = i;
  147.     ioa->ioa_Request.io_Device = (struct Device *)i;
  148.     ioa->ioa_Request.io_Unit = (struct Unit *)i;
  149. #ifdef __PPC__
  150. #ifdef WOS
  151.     FreeVecPPC(ioa);
  152. #else
  153.     PPCFreeVec(ioa);
  154. #endif
  155. #else
  156.     FreeVec(ioa);
  157. #endif
  158.   }
  159. }
  160.  
  161.  
  162. static void freechans(void)
  163. /* free MsgPorts and IOAudios of alls channels, close audio.device */
  164. {
  165.   int i;
  166.  
  167.   if (audio_dev==0 && aud_io) {
  168.     aud_io->ioa_Request.io_Unit = (struct Unit *)((1<<num_chans)-1);
  169.     CloseDevice((struct IORequest *)aud_io);
  170.     audio_dev = -1;
  171.   }
  172.   for (i=0; i<ADHARD_CHANNELS; i++) {
  173.     if (chans[i].audio) {
  174.       free_ioaudio(chans[i].audio);
  175.       chans[i].audio = NULL;
  176.     }
  177.     if (chans[i].audmp) {
  178.       DeletePort(chans[i].audmp);
  179.       chans[i].audmp = NULL;
  180.     }
  181.   }
  182.   num_chans = 0;
  183.   if (aud_io) {
  184.     free_ioaudio(aud_io);
  185.     aud_io = NULL;
  186.   }
  187. }
  188.  
  189.  
  190. static void stop_channel(int ch)
  191. /* stop audio output for this channel */
  192. {
  193.   if (audio_dev == 0) {
  194.     if (chans[ch].audio) {
  195.       if (!(chans[ch].audio->ioa_Request.io_Message.mn_Node.ln_Type))
  196.         return;
  197.       if (!CheckIO((struct IORequest *)chans[ch].audio))
  198.         AbortIO((struct IORequest *)chans[ch].audio);
  199.       WaitPort(chans[ch].audmp);
  200.       while (GetMsg(chans[ch].audmp));
  201.     }
  202.   }
  203. }
  204.  
  205.  
  206. /*
  207.  * ================== PUBLIC FUNCTIONS =====================
  208.  */
  209.  
  210.  
  211. int Snd_init(int num_snd,Sample *sa,int frequency,
  212.              int channels, const char *dev)
  213. /* Set up sound system with number of channels and number of samples. */
  214. /* The Sample structure must have already been initialized. */
  215. {
  216.   char *snderr = "Snd_init: ";
  217.   struct GfxBase *gfxb;
  218.   long clock;
  219.   int i,success=0;
  220.  
  221.   Snd_restore();
  222.   if (channels > ADHARD_CHANNELS) {
  223.     fprintf(stderr,"%sPaula doesn't support more than %d channels.\n",
  224.             snderr,ADHARD_CHANNELS);
  225.     return (0);
  226.   }
  227.   else if (channels==0 || num_snd==0)
  228.     return (1);
  229.   for (i=0; i<num_snd; sa[i++].cdata = NULL);
  230.  
  231.   /* determine clock constant */
  232.   if (gfxb = (struct GfxBase *)OpenLibrary("graphics.library",36)) {
  233.     clock = (gfxb->DisplayFlags & PAL) ? 3546895 : 3579545;
  234.     CloseLibrary((struct Library *)gfxb);
  235.   }
  236.   else {
  237.     fprintf(stderr,"%sgraphics.library V36 required!\n",snderr);
  238.     return (0);
  239.   }
  240.   playback_period = (UWORD)(clock/(long)frequency);
  241.  
  242.   for (i=0; i<channels; i++) {
  243.     if (!(chans[i].audmp = CreatePort(NULL,0))) {
  244.       fprintf(stderr,"%sCan't create MsgPort for channel %d.\n",snderr,i);
  245.       freechans();
  246.       return (0);
  247.     }
  248.   }
  249.   if (aud_io = alloc_ioaudio()) {
  250.     chmask = (1<<channels)-1;
  251.     aud_io->ioa_Request.io_Message.mn_ReplyPort = chans[0].audmp;
  252.     aud_io->ioa_Request.io_Message.mn_Node.ln_Pri = ADALLOC_MAXPREC;
  253.     aud_io->ioa_Request.io_Command = ADCMD_ALLOCATE;
  254.     aud_io->ioa_Request.io_Flags = ADIOF_NOWAIT;
  255.     aud_io->ioa_AllocKey = 0;
  256.     aud_io->ioa_Data = &chmask;
  257.     aud_io->ioa_Length = 1;
  258.  
  259.     if (!(audio_dev = OpenDevice(AUDIONAME,0,
  260.                                  (struct IORequest *)aud_io,0))) {
  261.       success = 1;
  262.       for (i=0; i<channels; i++) {
  263.         /* allocate audio channels */
  264.         if (chans[i].audio = alloc_ioaudio()) {
  265.           *chans[i].audio = *aud_io;
  266.           chans[i].audio->ioa_Request.io_Message.mn_ReplyPort =
  267.                                                  chans[i].audmp;
  268.           chans[i].audio->ioa_Request.io_Message.mn_Node.ln_Type = 0;
  269.           chans[i].audio->ioa_Request.io_Unit = (struct Unit *)(1 << i);
  270.         }
  271.         else {
  272.           fprintf(stderr,"%sCan't alloc IOAudio for channel %d.\n",snderr,i);
  273.           success = 0;
  274.           break;
  275.         }
  276.       }
  277.  
  278.       if (success) {
  279.         num_chans = channels;
  280.         sounds = sa;
  281.         num_sounds = num_snd;
  282.         for (i=0; i<num_snd; i++) {
  283.           /* convert and allocate samples for all sounds */
  284.           if (!(sa[i].cdata = get_chip_sample(&sa[i]))) {
  285.             fprintf(stderr,"%sCan't alloc Chip RAM for sample %d.\n",
  286.                     snderr,i);
  287.             success = 0;
  288.             break;
  289.           }
  290.         }
  291.       }
  292.     }
  293.     else
  294.       fprintf(stderr,"%sCan't access %s for %d channels.\n",
  295.               snderr,AUDIONAME,channels);
  296.   }
  297.   else
  298.     fprintf(stderr,"%sCan't alloc first IOAudio.\n",snderr);
  299.  
  300.   if (!success) {
  301.     free_chip();
  302.     freechans();
  303.     return (0);
  304.   }
  305.   return (1);
  306. }
  307.  
  308.  
  309. int Snd_restore(void)
  310. {
  311.   int i;
  312.  
  313.   for (i=0; i<ADHARD_CHANNELS; stop_channel(i++));
  314.   free_chip();
  315.   freechans();
  316.   return (0);
  317. }
  318.  
  319.  
  320. int Snd_effect(int sound_num, int channel)
  321. {
  322.   struct IOAudio *ioa;
  323.   Sample *s;
  324.  
  325.   if (channel<0 || channel>=ADHARD_CHANNELS || sound_num < 0
  326.       || sound_num >= num_sounds || audio_dev)
  327.     return (1);
  328.   if (sounds[sound_num].data == NULL || sounds[sound_num].cdata == NULL) {
  329.     fprintf(stderr,"Snd_effect: Referencing NULL sound entry in "
  330.                    "sound #%d.\n",sound_num);
  331.     return (1);
  332.   }
  333.  
  334.   stop_channel(channel);
  335.   ioa = chans[channel].audio;
  336.   s = &sounds[sound_num];
  337.   ioa->ioa_Request.io_Command = CMD_WRITE;
  338.   ioa->ioa_Request.io_Flags = ADIOF_PERVOL;
  339.   ioa->ioa_Data = (UBYTE *)s->cdata;
  340.   ioa->ioa_Length = (ULONG)s->len;
  341.   ioa->ioa_Period = playback_period;
  342.   ioa->ioa_Volume = 64;
  343.   ioa->ioa_Cycles = s->loop ? 0 : 1;
  344.  
  345.   BeginIO((struct IORequest *)ioa);
  346.   return (0);
  347. }
  348.  
  349.  
  350. int Snd_loadRawSample(const char *file, Sample *sample, int loop)
  351. /* given the name of a .raw sound file, load it into the Sample struct */ 
  352. /* pointed to by 'sample'                                              */
  353. /* Returns -1 couldn't open/read file                                  */
  354. /*         -2 couldn't alloc memory)                                   */
  355. {
  356.   int ret = 0;
  357.   FILE *fp;
  358.  
  359.   free_sample(sample);
  360.   sample->loop = loop;
  361.   if (fp = fopen(file,"r")) {
  362.     fseek(fp,0,SEEK_END);
  363.     sample->len = (int)ftell(fp);
  364.     fseek(fp,0,SEEK_SET);
  365.     if (sample->data = (unsigned char *)malloc(sample->len)) {
  366.       fread(sample->data,1,sample->len,fp);
  367.       if (!(sample->cdata = get_chip_sample(sample)))
  368.         ret = -2;
  369.     }
  370.     else
  371.       ret = -2;
  372.     fclose(fp);
  373.   }
  374.   else
  375.     ret = -1;
  376.   if (ret)
  377.     free_sample(sample);
  378.   return (ret);
  379. }
  380.